'use strict';

/**
* Created at 16/7/8.
* @Author Ling.
* @Email i@zeroling.com
*/

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _values = require('babel-runtime/core-js/object/values');

var _values2 = _interopRequireDefault(_values);

var _getIterator2 = require('babel-runtime/core-js/get-iterator');

var _getIterator3 = _interopRequireDefault(_getIterator2);

var _stringify = require('babel-runtime/core-js/json/stringify');

var _stringify2 = _interopRequireDefault(_stringify);

var _keys = require('babel-runtime/core-js/object/keys');

var _keys2 = _interopRequireDefault(_keys);

var _path = require('path');

var _path2 = _interopRequireDefault(_path);

var _gracefulFs = require('graceful-fs');

var _gracefulFs2 = _interopRequireDefault(_gracefulFs);

var _glob = require('glob');

var _glob2 = _interopRequireDefault(_glob);

var _log = require('./retcodelog/src/log.js');

var _log2 = _interopRequireDefault(_log);

var _babylon = require('babylon');

var _utils = require('./utils');

var _debug = require('debug');

var _debug2 = _interopRequireDefault(_debug);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var debug = (0, _debug2.default)('next:collect');exports.default = {
  collectDetail: collectDetail,
  collectBrief: collectBrief
};

/**
* 收集简单埋点
*/

function collectBrief(projectId, key, others) {
  try {
    // 打点类数据
    var msg = (0, _utils.getMacAddress)() + '__' + projectId + '__' + key;
    if (others) {
      msg += '__' + others;
    }
    _log2.default.custom(1, msg);
  } catch (error) {
    console.log(error);
  }
}

/**
* 分析数据
*/
function collect(options, pkjson) {
  debug('options', options);
  options = options || {};
  var rootDir = void 0;

  if (Object.prototype.toString.call(options) == '[object String]') {
    rootDir = options;
    options = {};
  }

  rootDir = rootDir || options.rootDir;

  if (!rootDir) {
    console.error('缺少项目路径，请添加 rootDir 参数');
    return;
  }

  options.rootDir = rootDir;
  var basicPackage = pkjson || '@alifd/next';
  options.businessComponentsRegExp = options.businessComponentsRegExp || /^@alifd\/next-/;

  if (['[object RegExp]', '[object Array]'].indexOf(Object.prototype.toString.call(options.businessComponentsRegExp)) === -1) {
    console.error('businessComponentsRegExp 必须为正则或者数组');
    return;
  }

  // 获取基础信息
  var pkg = {};
  try {
    var packageFilePath = _path2.default.join(rootDir, 'package.json');
    pkg = JSON.parse(_gracefulFs2.default.readFileSync(packageFilePath, 'utf-8'));
  } catch (err) {
    debug('读取 package.json 文件错误: ', err.message);
  }

  var gitConfig = (0, _utils.getGitConfig)(rootDir);
  var modules = (0, _utils.getDepsInfo)(rootDir, pkg);

  debug('git config', gitConfig);
  debug('项目依赖信息', modules);

  var analyzeFiles = _glob2.default.sync('**/*.js?(x)', {
    cwd: rootDir,
    ignore: ['**/node_modules/**', 'build/**', 'assets/build/**', 'dist/**', '_output/**', '**.config.js']
  });

  debug('目标文件：', analyzeFiles);

  var analyzed = analyzeFiles.reduce(function (obj, current) {
    var analyzeRes = analyze(_path2.default.join(rootDir, current));
    if (analyzeRes) {
      obj[current] = analyzeRes;
    }
    return obj;
  }, {});

  debug('依赖分析：', analyzed);

  var repoName = void 0;
  if (process.env.BUILD_GIT_GROUP && process.env.BUILD_GIT_PROJECT) {
    repoName = process.env.BUILD_GIT_GROUP + '/' + process.env.BUILD_GIT_PROJECT;
  }

  var basicPackageVersion = void 0;

  try {
    var basicPkgjsonPath = _path2.default.join(rootDir, 'node_modules', basicPackage, 'package.json');
    if (_gracefulFs2.default.existsSync(basicPkgjsonPath)) {
      var basicPkgjson = _gracefulFs2.default.readFileSync(basicPkgjsonPath, 'utf-8');
      var basicPkg = JSON.parse(basicPkgjson);
      basicPackageVersion = basicPkg && basicPkg.version;
    } else {
      basicPackageVersion = pkg['dependencies'][basicPackage] || '';
    }
  } catch (error) {
    console.error(error);
  }
  debug('被统计的插件版本：', basicPackageVersion);

  var result = {
    // 云构建读取出来的可能是 工号 也可能是 花名，云构建读取数据的优先级高于 git config
    author: gitConfig.userName,
    // 项目组名和仓库名
    repoName: repoName || gitConfig.repoName,
    // 仓库地址
    gitUrl: gitConfig.url,
    // 统计工具名称
    kit: options.kit || 'fusion-collector',
    // 主体包名称
    basicPackage: basicPackage,
    // 主体包版本信息
    basicPackageVersion: basicPackageVersion,
    // package.json 信息
    pkg: pkg,
    // 模块依赖信息
    modules: modules,
    // 依赖信息分析
    analyzed: analyzed,
    // 主体包信息统计
    statistics: getStatistics(analyzed, basicPackage, options.businessComponentsRegExp)
  };

  debug('上报数据', result);

  return result;
}

/**
* 格式化数据收集
*/
function formatCollect(originInfo) {
  return {
    author: originInfo.author,
    repoName: originInfo.repoName,
    gitUrl: originInfo.gitUrl,
    kit: originInfo.kit,
    basicPackage: originInfo.basicPackage,
    basicPackageVersion: originInfo.basicPackageVersion,
    basicComponentsTimes: originInfo.statistics ? originInfo.statistics.basicComponentsTimes : {},
    pkg: {
      name: originInfo.pkg ? originInfo.pkg.name : '',
      description: originInfo.pkg ? originInfo.pkg.description : '',
      dependencies: originInfo.pkg.dependencies
    }
  };
}

/**
* 分析并上报数据,recode使用get上报，数据量如果大的话需要拆分请求。
*/
function collectDetail(options) {
  var retCodeInfo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  try {
    var basePkg = Array.isArray(options.basicPackage) ? options.basicPackage : [options.basicPackage];

    basePkg.forEach(function (pkjson) {

      var originInfo = collect(options, pkjson);
      var uploadInfo = formatCollect(originInfo);

      _log2.default.setConfig({
        sample: retCodeInfo.sample || 1,
        spmId: retCodeInfo.spmId || 'fusion.next'
      });

      var logMsg = '';
      if (uploadInfo.basicPackageVersion === '' && (0, _keys2.default)(uploadInfo.basicComponentsTimes).length < 1) {
        return false;
      } else {
        (0, _keys2.default)(uploadInfo).forEach(function (key) {
          logMsg += key + '=' + (0, _stringify2.default)(uploadInfo[key]) + '&&';
        });
        // 可分析类数据
        _log2.default.log(logMsg, 1);

        return true;
      }
    });
  } catch (error) {
    console.log(error);
  }
}

/**
* 分析文件依赖
*/
function analyze(file) {
  try {
    var source = _gracefulFs2.default.readFileSync(file, 'utf-8');
    var ast = (0, _babylon.parse)(source, {
      sourceType: 'module',
      plugins: ['jsx', 'flow', 'asyncFunctions', 'classConstructorCall', 'doExpressions', 'trailingFunctionCommas', 'objectRestSpread', 'decorators', 'classProperties', 'exportExtensions', 'exponentiationOperator', 'asyncGenerators', 'functionBind', 'functionSent']
    });
    // got ast
    return (0, _utils.getImportedOrRequiredModules)(ast);
  } catch (err) {
    return null;
  }
}
/**
* 根据依赖信息做进一步计算统计
*/
function getStatistics(analyzed, basicPackage, businessComponentsRegExp) {
  var basicComponentsTimes = {}; // 基础组件引用次数
  var businessComponentsTimes = {}; // 业务组件引用次数
  var thirdModulesTimes = {}; // 第三方模块引用次数

  function isBusinessComponent(moduleName) {
    if (Object.prototype.toString.call(businessComponentsRegExp) === '[object RegExp]') {
      return businessComponentsRegExp.test(moduleName);
    }

    return businessComponentsRegExp.indexOf(moduleName) > -1;
  }

  var _iteratorNormalCompletion = true;
  var _didIteratorError = false;
  var _iteratorError = undefined;

  try {
    for (var _iterator = (0, _getIterator3.default)((0, _values2.default)(analyzed)), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var arr = _step.value;

      arr.forEach(function (imported) {
        if (imported.fromModule === basicPackage) {
          // 基础组件
          if (Array.isArray(imported.importedValue)) {
            imported.importedValue.forEach(function (moduleName) {
              basicComponentsTimes[moduleName] = basicComponentsTimes[moduleName] === undefined ? 1 : basicComponentsTimes[moduleName] + 1;
            });
          } else {
            basicComponentsTimes[imported.importedValue] = basicComponentsTimes[imported.importedValue] === undefined ? 1 : basicComponentsTimes[imported.importedValue] + 1;
          }
        } else if (isBusinessComponent(imported.fromModule)) {
          // 业务组件
          businessComponentsTimes[imported.fromModule] = businessComponentsTimes[imported.fromModule] === undefined ? 1 : businessComponentsTimes[imported.fromModule] + 1;
        } else {
          // 第三方模块
          thirdModulesTimes[imported.fromModule] = thirdModulesTimes[imported.fromModule] === undefined ? 1 : thirdModulesTimes[imported.fromModule] + 1;
        }
      });
    }
  } catch (err) {
    _didIteratorError = true;
    _iteratorError = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion && _iterator.return) {
        _iterator.return();
      }
    } finally {
      if (_didIteratorError) {
        throw _iteratorError;
      }
    }
  }

  return {
    basicComponents: (0, _keys2.default)(basicComponentsTimes),
    businessComponents: (0, _keys2.default)(businessComponentsTimes),
    thirdModules: (0, _keys2.default)(thirdModulesTimes),
    basicComponentsTimes: basicComponentsTimes,
    businessComponentsTimes: businessComponentsTimes,
    thirdModulesTimes: thirdModulesTimes
  };
}
module.exports = exports['default'];